package cn.com.twoke.game.server;

import cn.com.twoke.game.common.constants.MessageType;
import cn.com.twoke.game.common.entity.message.LoginMessage;
import cn.com.twoke.game.common.entity.message.Message;
import cn.com.twoke.game.common.handler.MessageHandler;
import cn.com.twoke.game.common.utils.MessageUtil;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.*;

public class GameServerManager implements Runnable {

    private Selector selector;
    private ServerSocketChannel serverSocketChannel;
    private Map<Integer, MessageHandler<? super Message>> listeners;

    public GameServerManager() {
        try {
            this.listeners = new HashMap<>();
            selector = Selector.open();
            // 创建一个ServerSocketChannel并绑定到指定的端口
            serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.bind(new InetSocketAddress(9999));
            // 设置为非阻塞模式
            serverSocketChannel.configureBlocking(false);
            // 将ServerSocketChannel注册到Selector上，并监听OP_ACCEPT事件
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("服务器已启动，等待客户端连接...");
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void on(MessageType messageType, MessageHandler listener) {
        System.out.println("registered: " + listener);
        this.listeners.put(messageType.getType(),listener);
    }

    @Override
    public void run() {
        try {
            while (true) {
                // 阻塞，等待事件发生
                selector.select();

                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
                while (keyIterator.hasNext()) {
                    SelectionKey key = keyIterator.next();

                    if (key.isAcceptable()) {     // 处理连接请求事件
                        SocketChannel client = serverSocketChannel.accept();
                        client.configureBlocking(false);
                        //监听OP_ACCEPT事件
                        client.register(selector, SelectionKey.OP_READ);
                    } else if (key.isReadable()) {
                        SocketChannel client = (SocketChannel) key.channel();
                        client.getRemoteAddress();
                        Message message =  MessageUtil.readMessage(client);
                        if (null != message) {
                            MessageHandler<? super Message> messageHandler = listeners.get(message.getType().getType());
                            if (messageHandler != null) {
                                messageHandler.handle(selector, client, message);
                            }
                        }
                    }
                    keyIterator.remove();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void writeMessage(Selector selector, SocketChannel client) throws IOException {
        Scanner scanner = new Scanner(System.in);
        String message = scanner.nextLine();
        MessageUtil.writeMessage(client, new LoginMessage(message));
        //  重新监听OP_ACCEPT事件
        client.register(selector, SelectionKey.OP_READ);
    }
}